package org.ccay.security.reaml;

import org.apache.shiro.authc.AuthenticationException;
import org.apache.shiro.authc.AuthenticationInfo;
import org.apache.shiro.authc.AuthenticationToken;
import org.apache.shiro.authc.LockedAccountException;
import org.apache.shiro.authc.SimpleAuthenticationInfo;
import org.apache.shiro.authc.UnknownAccountException;
import org.apache.shiro.authz.AuthorizationInfo;
import org.apache.shiro.realm.AuthorizingRealm;
import org.apache.shiro.subject.PrincipalCollection;
import org.apache.shiro.util.ByteSource;
import org.ccay.core.request.Application;
import org.ccay.security.authc.DefaultProgramAuthorizationInfo;
import org.ccay.security.authc.UserInfoPasswordToken;
import org.ccay.security.entity.User;

/**
 * shiro的自定义Reaml 
 * @author chaowangbang
 * @since 2017年2月5日
 */
public class Reaml extends AuthorizingRealm{
	
	private ISecurityInfoProvider securityInfoProvider;


	public void setSecurityInfoProvider(ISecurityInfoProvider securityInfoProvider) {
		this.securityInfoProvider = securityInfoProvider;
	}

	@Override
	protected AuthorizationInfo doGetAuthorizationInfo(
			PrincipalCollection principals) {
		 User user = (User)principals.getPrimaryPrincipal();
		 DefaultProgramAuthorizationInfo authorizationInfo = new DefaultProgramAuthorizationInfo();
		 //装载范围角色信息
		 authorizationInfo.setProgramRoles(securityInfoProvider.findProgramRoles(user,Application.getCurrent()));
         //装载权限信息
		 authorizationInfo.setObjectPermissions(securityInfoProvider.findPermissions(authorizationInfo.getRoleIds(),user,Application.getCurrent()));
         return authorizationInfo;
	}

	/**
	 * 具有缓存支持的权限信息获取
	 * @param principals
	 * @return
	 */
	public AuthorizationInfo getCachedAuthorizationInfo(PrincipalCollection principals){
		return super.getAuthorizationInfo(principals);
	}
	
	
	@Override
	protected AuthenticationInfo doGetAuthenticationInfo(
			AuthenticationToken authenToken) throws AuthenticationException {
		UserInfoPasswordToken token = (UserInfoPasswordToken)authenToken;
		//传入的
		User principal = (User)token.getPrincipal();
		//数据库查找到的用户信息
        User user = securityInfoProvider.findAuthenticationInfo(principal);
        if(user == null) {
            throw new UnknownAccountException();//没找到帐号
        }
        if(!user.getEnabled()) {
            throw new LockedAccountException(); //帐号锁定
        }
        //合并用户信息
        mergeUserInfo(principal,user);
        //盐算法必须使用java.security.SecureRandom生成
		SimpleAuthenticationInfo authenticationInfo = new SimpleAuthenticationInfo(
				principal,principal.getPassword(),ByteSource.Util.bytes(principal.getSalt()),getName());
		
        return authenticationInfo;
	}
	
	/**
	 * 将数据库信息合并到tokenPrincipal
	 * @param principal
	 * @param dbInfo
	 */
	protected void mergeUserInfo(User principal,User dbInfo){
		principal.setId(dbInfo.getId());
		principal.setDisplayName(dbInfo.getDisplayName());
		principal.setEmail(dbInfo.getEmail());
		principal.setPhone(dbInfo.getPhone());
		principal.setPassword(dbInfo.getPassword());
		principal.setSalt(dbInfo.getSalt());
		principal.setEnabled(dbInfo.getEnabled());
		principal.setDeleted(dbInfo.getDeleted());
		principal.setExpireDate(dbInfo.getExpireDate());
	}
	@Override
	public boolean supports(AuthenticationToken token){
		 return token instanceof UserInfoPasswordToken;
	 }
	
    protected Object getAuthenticationCacheKey(AuthenticationToken authenToken) {
    	if(authenToken == null){
    		return null;
    	}
    	UserInfoPasswordToken token = (UserInfoPasswordToken)authenToken;
    	User principal = (User)token.getPrincipal();
    	return principal.getCacheKey();
    }
    
    protected Object getAuthorizationCacheKey(PrincipalCollection principals) {
    	User principal = (User)principals.getPrimaryPrincipal();
    	return principal.getCacheKey();
    }
}
